package demo.socket;

import org.wevil.util.DateUtil;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

/**
 * BIO单线程模型
 * */
public class BIO1ThreadServer {
    public static void main(String[] args) throws IOException, InterruptedException {
        // 1. 创建SocketServer端
        final ServerSocket serverSocket = new ServerSocket(8900);
        while (true) {
            // 2. 等待客户端建立链接
            // 这一步线程阻塞，等待客户端连接，但是在jvm里查看线程仍然是running状态
            // 这是因为从Java线程状态的角度来看，这个线程仍然是RUNNABLE的，
            // 因为它正在等待的是操作系统层面的资源，而不是Java层面上的锁或条件
            final Socket clientSocket = serverSocket.accept();
            System.out.println(DateUtil.getTimeStr() + " Accepted connection from " + clientSocket);
            // 3. 读取客户端发送的消息
            InputStream in = clientSocket.getInputStream();
            OutputStream out;
            // 4. 等待接收数据
            DataInputStream dis = new DataInputStream(in);
            int len;
            byte[] bytes = new byte[256];
            // 输入流到达末尾，可以读取到-1
            // 但并不是客户端输入完一次就算到文件流末尾
            // 对于网络输入流（如Socket的输入流），当对方关闭连接或发送完数据并关闭其输出流时，输入流才到达末尾。
            // 也就是客户端端开连接时才算到达文件流末尾
            while ((len = dis.read(bytes)) != -1) {
                String content = new String(bytes, 0, len);
                System.out.println(DateUtil.getTimeStr() + " 接收数据：" + content);
                // 暂停10秒，模拟服务端处理业务
                Thread.sleep(1000*10);
                // 读取完256个字节后就默认读取完成，跳出循环
                break;
            }
            // 5. 回复数据
            out = clientSocket.getOutputStream();
            System.out.println(DateUtil.getTimeStr() + " 回复数据：Hi!");
            out.write("Hi!\r\n".getBytes(StandardCharsets.UTF_8));
            out.flush();
            // 6. 关闭链接，服务端主动断链接
            clientSocket.close();
        }
    }
}
